/**
 * File Name: Orka.java
 *
 * Date: 18/12/2009
 *
 * Copyright (c) 2006 Michael LaLena. All rights reserved.  (www.lalena.com)
 * Permission to use, copy, modify, and distribute this Program and its documentation,
 *  if any, for any purpose and without fee is hereby granted, provided that:
 *   (i) you not charge any fee for the Program, and the Program not be incorporated
 *       by you in any software or code for which compensation is expected or received;
 *   (ii) the copyright notice listed above appears in all copies;
 *   (iii) both the copyright notice and this Agreement appear in all supporting documentation; and
 *   (iv) the name of Michael LaLena or lalena.com not be used in advertising or publicity
 *          pertaining to distribution of the Program without specific, written prior permission.
 */
package model;

import gui.Constanten;
import java.awt.*;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import java.util.Random;

/**
 * Afgeleide klasse van Dier
 * Bevat de eigenschappen en methodes van hoe een orka zich gedraagt tov zijn omgeving
 *
 * @author Michiel Declercq
 * @author Stijn Delbeke
 * @author Dieter Deriemaeker
 * @author Gregory Nickmans
 *
 * @author Michael LaLena
 *
 */
public class Orka extends Dier {

    /**
     * Random generator
     */
    private static Random rand = new Random();

    /**
     * Constructor
     *
     * @param  x x-coördinaat
     * @param  y y-coördinaat
     */
    public Orka(int x, int y) {
        super(x, y, Constanten.GROOTTE_ORKA, (int) (Math.random() * 360), Constanten.KLEUR_ORKA);

        this.setCurrentSpeed(rand.nextDouble() * Constanten.MAX_SNELHEID_ORKA);
        while (this.getCurrentSpeed() <= Constanten.MAX_SNELHEID_ORKA - Constanten.MAX_SNELHEID_VIS) {
            this.setCurrentSpeed(rand.nextDouble() * Constanten.MAX_SNELHEID_ORKA);
        }
        this.setMaxTurnTheta(Constanten.MAX_THETA_ORKA);

        Aquarium.aantalOrkas++;
    }

    /**
     * Het gedrag van een orka
     * Is het dichtst bijzijnde object een obstakel of orka, ontwijk
     * Is dit een vis, ga naar deze toe
     *
     * @param anderObject een object binnen de omgeving
     * @param target Som van de posities van alle objecten binnen het zicht
     * @return Point
     */
    public Point Handling(AquariumObject anderObject, Point target) {
        Point otherLocation = closestLocation(this.location, anderObject.location);
        int distance = this.getDistance(otherLocation);

        if (!(this.equals(anderObject)) && (distance > 0) && distance <= DetectionRange) {
            //Ander object is ook een vis en is binnen het bereik
            //->Aligneren
            if ((anderObject instanceof Vis)) {
                Point dist = sumPoints(this.location, -1.0, otherLocation, 1.0);
                dist = normalisePoint(dist, 1000);
                double weight = 1;

                target = sumPoints(target, 1.0, dist, weight); // weight is variable
            }
            //Ander object is een Orka
            //->Botsing vermijden
            else if (anderObject instanceof Orka) {
                Point dist = sumPoints(this.location, 1.0, otherLocation, -1.0);
                dist = normalisePoint(dist, 1000);
                double weight = Math.pow((1 - (double) distance / DetectionRange), 2);
                target = sumPoints(target, 1.0, dist, weight); // weight is variable
            }
            //Ander object is een Obstakel
            //->Vermijden
            else if (anderObject instanceof Obstakel) {
                double r = Constanten.DETECTION_DISTANCE;
                Ellipse2D ell = new Ellipse2D.Double(this.location.x - r, this.location.y - r, 2 * r, 2 * r);
                Rectangle2D rect = ell.getBounds2D();
                Obstakel obst = (Obstakel) anderObject;
                if (rect.intersects(obst.location.x, obst.location.y, obst.size.width, obst.size.height)) {
                    Point dist = sumPoints(this.location, 1.0, obst.getCenter(), -1.0);
                    dist = normalisePoint(dist, 1000);
                    double weight = 10 * Math.pow((1 - (double) distance / DetectionRange), 2);
                    target = sumPoints(target, 1.0, dist, weight); // weight is variable
                }
            }
            //Random: richting behouden of willekeurige richting aannemen
            else {
                if (rand.nextBoolean()) {
                    target = sumPoints(target, 1.0, new Point(rand.nextInt(), rand.nextInt()), distance);
                }
            }
        }
        return target;
    }
}
